using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;

namespace ADDDF.Infrastructure
{   
    /// <summary>
    /// A KeyAssignableEntityBase is an entity (implements IEntity) which implements
    /// the IAllowKeyAssignment interface. It is for an entity which uses the 
    /// "two-stage key assignment" design pattern.
    /// 
    /// Pure DDD requires that an entity should be assigned a key when it is
    /// created, and the key should stay with it until its life-cycle ends. However,
    /// it is common to use database assigned ID as the key of an entity. It is possible
    /// to get a new key from the database every time when an entity is created. The 
    /// problems with this include:
    /// 1. Some database does not allow you to get a unique ID for a table until the
    ///    data is inserted into it. You might have to create your own unique ID 
    ///    machanism. One way is to create a unique-ID table. This is a burden.
    /// 2. Obtaining a database generated ID when the entity is created requires a
    ///    extra trip to the database which seems unnecessary, and hurts performance. 
    ///
    /// The two-stage key assignment method is a convention in which when the entity
    /// is created it gets a temporary key, which should be unique across all entity
    /// types, and not just unique among one specific entity type. Once the entity is
    /// added in to the repository, it gets a permanant key which is assigned by the
    /// database.
    /// 
    /// The problem with two-stage key assignment is that an entity with a temporary
    /// key, and the same instance of the entity with a permanant key are considered 
    /// to be different entities in pure DDD. Curretly this is the limitation of this 
    /// approach, and the implementor need to be aware of it.
    /// 
    /// Using two-stage key assignment, a repository can check for whether the 
    /// entity implements the IAllowKeyAssignment interface, and if it does then it
    /// will assign the database generated ID to the key when the entity is added into
    /// the repository.
    /// 
    /// Currently, I don't see a reason to distinquish between a temporary key and a
    /// permanant key. The framework uses Object.Equals() to compare entity keys because
    /// they are value-objects (see IEntityKey). 
    /// </summary>
    public abstract class KeyAssignableEntityBase : EntityBase, IAllowKeyAssignment
    {
        #region Construcotrs

        /// <summary>
        /// Create an entity with a key. 
        /// </summary>
        /// <param name="key">Key of an entity. Cannot be null.</param>
        protected KeyAssignableEntityBase(object key)
            : base(key)
        {
        }

        #endregion

        #region IAllowKeyAssignment

        void IAllowKeyAssignment.AssignKey(object key)
        {
            base.SetKey(key);
        }

        #endregion
    }
}
